/*
 * @Author: zhong_m
 * @Date: 2021-11-24 18:42:32
 * @LastEditTime: 2021-12-28 19:38:26
 * @LastEditors: zhong_m
 * @Description: 切换主题（仅对<style>标签内样式有效
 * @FilePath: \central-system\src\utils\theme.js
 */
import {theme} from '@/config'

// 浅色组浅度列表
let alphaList = []

function insertAfter(el, tag) {
	 return el.nextSibling ? el.parentNode.insertBefore(tag, el.nextSibling) : el.parentNode.appendChild(tag)
}

function getCSSString(url) {
	return new Promise(resolve => {
		const xhr = new XMLHttpRequest()
		xhr.onreadystatechange = () => {
			if (xhr.readyState === 4 && xhr.status === 200) {
				resolve(xhr.responseText.replace(/@font-face{[^}]+}/, ''))
			}
		}
		xhr.open('GET', url)
		xhr.send()
	})
}
// 获取主题色组
function getThemeCluster(theme, fix = 100) {
	const tintColor = (color, tint) => {
		let red = parseInt(color.slice(1, 3), 16)
		let green = parseInt(color.slice(3, 5), 16)
		let blue = parseInt(color.slice(5), 16)
		if (tint === 0) {
			// when primary color is in its rgb space
			return [red, green, blue].join(',')
		} else {
			red += Math.round(tint * (255 - red))
			green += Math.round(tint * (255 - green))
			blue += Math.round(tint * (255 - blue))
			red = red.toString(16)
			green = green.toString(16)
			blue = blue.toString(16)
			return `#${red}${green}${blue}`
		}
	}
	const shadeColor = (color, shade) => {
		let red = parseInt(color.slice(1, 3), 16)
		let green = parseInt(color.slice(3, 5), 16)
		let blue = parseInt(color.slice(5), 16)
		red = Math.round((1 - shade) * red)
		green = Math.round((1 - shade) * green)
		blue = Math.round((1 - shade) * blue)
		red = red.toString(16)
		green = green.toString(16)
		blue = blue.toString(16)
		return `#${red}${green}${blue}`
	}
	const clusters = [theme]
	// 已有浅色系列表直接使用
	if (alphaList.length) {
		alphaList.forEach(item => {
			clusters.push(tintColor(theme, item))
		})
	} else { // 用于获取所有透明度
		for (let i = 1; i < fix; i++) {
			clusters.push(tintColor(theme, Number((i / fix).toFixed(2))))
		}
	}
	clusters.push(shadeColor(theme, 0.1))
	return clusters
}

// 获取使用的浅色系
function getAlphaList(color) {
	const styles = [].slice.call(document.querySelectorAll('head style'))
	let cluster = getThemeCluster(color, 100)
	let useColorAlpha = []
	styles.forEach(style => {
		let { innerText } = style
		if (typeof innerText !== 'string') return
		cluster.forEach((color, index) => {
			if (new RegExp(color,'ig').test(innerText)) {
				cluster.splice()
				useColorAlpha.push([cluster[index], index])
			}
		})
	})
	alphaList = []
	new Set(useColorAlpha.filter(item => item[1] > 0 && item[1] < 100)).forEach(item => {
		alphaList.push(item[1] / 100)
	})
}
/**
 *  初始化，将css文件处理为style
 */
export async function themeInit() {
	for (const item of [...document.querySelectorAll('head link[rel=stylesheet]')]) {
		let text = await getCSSString(item.href)
		let styleTag = document.createElement('style')
		styleTag.innerText = text
		insertAfter(item, styleTag)
	}
}
/**
 * 更新style
 * @param {string} ntheme 新主题
 * @param {string} otheme 旧主题
 */
export function updateStyle(ntheme, otheme = theme) {
	const styles = [].slice.call(document.querySelectorAll('head style'))
	const orgb = [
		parseInt(otheme.slice(1, 3), 16),
		parseInt(otheme.slice(3, 5), 16),
		parseInt(otheme.slice(5), 16)
	]
	const alphaToHex = alpha => {
		let hex = parseInt(alpha * 255)
			.toString(16)
			.toUpperCase()

		return hex.length > 1 ? hex : '0' + hex
	}
	if (!alphaList.length) {
		getAlphaList(otheme)
	}
	const originalCluster = getThemeCluster(otheme)
	const themeCluster = getThemeCluster(ntheme)
	styles.forEach(style => {
		let { innerText } = style
		if (typeof innerText !== 'string') return
		originalCluster.forEach((color, index) => {
			const ncolor = themeCluster[index]
			if (new RegExp(color,'ig').test(innerText)) {
				innerText = innerText.replace(new RegExp(color, 'ig'), ncolor)
			}
		})
		// 更新rgba类颜色
		style.innerText = innerText.replace(
			new RegExp(`rgba\\(${orgb.join(',\\s?')}(,(.+?))?\\)`, 'ig'),
			(...match) => {
				return `${ntheme}${alphaToHex(match[2])}`
			}
		)
	})
}
